/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package analiseSintatica.Regras.Expressoes;

import AnaliseLexicaFinal.EstruturaDeDados.LinkToken;
import analiseSintatica.ErroSintaticoException;
import analiseSintatica.ReconhecerTerminais;
import analiseSintatica.Regras.Regra;
import analiseSintatica.estruturadados.NoArvore;
import analiseSintatica.Regras.Tipos.RegraTipoPrimitivo;


import analiseSintatica.estruturadados.ErroSintatico;
import java.util.LinkedList;

/**
 *
 * @author matheus
 */
public class RegraCast extends Regra {

    protected static Regra instancia;

    // @Override
    protected String estrutura = "<unario_prefixa> | '(' <tipo_primitivo> ')' <cast>";
    

    /**
     * Construtor privado necessario ao singleton
     */
    private RegraCast() {
    }

    /**
     * Retorna a unica instancia dessa classe.
     * @return
     */
    public static RegraCast getInstance() {
        if (instancia == null) {
            instancia = new RegraCast();
        }
        return (RegraCast) instancia;
    }

    public NoArvore analisar(LinkedList<LinkToken> listaTokens) throws ErroSintaticoException {
        ErroSintaticoException erros = new ErroSintaticoException();

        NoArvore naoterminalcast = new NoArvore("<cast>", false);

        if ("(".equals(listaTokens.getFirst().getLexema()) && (RegraTipoPrimitivo.getInstance().getPrimeiro().contains(listaTokens.get(1).getLexema())||
                RegraTipoPrimitivo.getInstance().getPrimeiro().contains(listaTokens.get(1).getToken()))) {//lista de tokens que vem do analisador sintático

            naoterminalcast.adicionaFilho(reconheceLexema(listaTokens, "delimitador", "(",estrutura));
            try{
                naoterminalcast.adicionaFilho(RegraTipoPrimitivo.getInstance().analisar(listaTokens));
            }catch(ErroSintaticoException e){
                while (e.size() != 0) {
                    erros.addErros(e.getErros());
                }
            }
            try{
                naoterminalcast.adicionaFilho(reconheceLexema(listaTokens, "delimitador", ")",estrutura));
            }catch(ErroSintaticoException e){
                ErroSintatico erro = e.getErros();
                erro.setCorreto(estrutura);
                erros.addErros(erro);
                LinkedList<String> sincronizacao = RegraCast.getInstance().getPrimeiro();
                LinkedList<String> parentese = new LinkedList<String>();
                parentese.add(")");
                sincronizacao = getUniao(sincronizacao, parentese);
                while (!listaContem(sincronizacao, listaTokens.getFirst())) {
                    erros.addErros("Token " + listaTokens.getFirst().getToken() + " nao permitido", estrutura, listaTokens.getFirst().getLinha());
                    listaTokens.removeFirst();
                }
            }

            try{
                naoterminalcast.adicionaFilho(RegraCast.getInstance().analisar(listaTokens));
            }catch(ErroSintaticoException e){
                while (e.size() != 0) {
                    erros.addErros(e.getErros());
                }
            }
        }else{
            try{
                naoterminalcast.adicionaFilho(RegraUnarioPrefixa.getInstance().analisar(listaTokens));
            }catch(ErroSintaticoException e){
                while (e.size() != 0) {
                    erros.addErros(e.getErros());
                }
            }
        }

        if (erros.size() != 0) {
            throw erros;
        }
        
        return naoterminalcast;
    }

    protected void setPrimeiro() {
        //{'{'} U {identificador, "(", numeroInteiro , numeroFlutuante , charconst, '++', '--', '&', '*'}
        primeiro.add("(");
        primeiro.add("{");
        primeiro.add("identificador");
        primeiro.add("numeroInteiro");
        primeiro.add("numeroFlutuante");
        primeiro.add("charconst");
        primeiro.add("++");
        primeiro.add("--");
        primeiro.add("&");
        primeiro.add("*");
    }

    protected void setSeguinte() {
        // P<cast> U {"+" , "-"} U {"<" , "<=" , ">" , ">="} U {"==" , "!=" } U {&&}
       // U {'{'} U {identificador, "(", numeroInteiro , numeroFlutuante ,
        //charconst, '++', '--', '&', '*'}U {";", ",", "}" ")"}
        seguinte.addAll(primeiro);
        seguinte.add("+");
        seguinte.add("-");
        seguinte.add("<");
        seguinte.add("<=");
        seguinte.add(">");
        seguinte.add(">=");
        seguinte.add("==");
        seguinte.add("!=");
        seguinte.add("&&");
        seguinte.add(";");
        seguinte.add(",");
        seguinte.add("}");
        seguinte.add(")");


    }
}
